﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace ScrumSim
{
    public struct CollisionInfo
    {
        public GameObject.Side mSide;
        public Vector2 mPenetrationVector;
    }

    //-------------------------------------------------------------------

    public class GameObject : DrawableGameComponent
    {
        protected Texture2D     mSprite;
        protected Vector2       mPosition;
        protected Rectangle     mBoundingBox;
        protected Rectangle     mSubRect;

        protected bool mFlipX;
        protected bool mFlipY;

        protected Game1 mGame;

        public enum Side { NONE = 0x00000000, TOP = 0x00000001, RIGHT = 0x00000002, LEFT = 0x00000004, BOTTOM = 0x00000008 }

        //----get/set---------

        public Texture2D sprite
        {
            get { return mSprite; }
            set { mSprite = value; }
        }

        public Rectangle subrect
        {
            get { return mSubRect; }
            set { mSubRect = value; }
        }

        public Vector2 position
        {
            get { return mPosition; }
            set { mPosition = value; }
        }

        public Rectangle BBox
        {
            get { return mBoundingBox; }
            set { mBoundingBox = value; }
        }

        //--------------------------------------------

        public GameObject(Game1 pGame, string pTexture)
            : this(pGame, pTexture, new Vector2(0,0), new Rectangle(), new Rectangle())
        {
            mBoundingBox = mSprite.Bounds;
            mSubRect = mSprite.Bounds;
        }


        public GameObject(Game1 pGame, Texture2D pTexture)
            : this(pGame, "", new Vector2(0, 0), new Rectangle(), new Rectangle())
        {
            mSprite = pTexture;
            mBoundingBox = mSprite.Bounds;
            mSubRect = mSprite.Bounds;
            mFlipX = false;
            mFlipY = false;
        }

        public GameObject(Game1 pGame, string pTexture, Vector2 pPosition, Rectangle pRect, Rectangle pBbox) : base(pGame)
        {
            mGame = pGame;

            if(pTexture != "")
                mSprite = mGame.Content.Load<Texture2D>(pTexture);

            mBoundingBox = pBbox;
            mSubRect = pRect;
            mPosition = pPosition;
        }

        //--------------------------------------------

        public override void Draw(GameTime gameTime)
        {
            Vector2 lScreenPosition = new Vector2(mPosition.X, mPosition.Y);
            lScreenPosition.X -= mGame.GetLevel().GetDX();
            lScreenPosition.Y -= mGame.GetLevel().getY();

            SpriteEffects lEffect = SpriteEffects.None;

            if(mFlipX)
                lEffect |= SpriteEffects.FlipHorizontally;

            if (mFlipY)
                lEffect |= SpriteEffects.FlipVertically;

            mGame.spriteBatch.Draw(mSprite, lScreenPosition, mSubRect, Color.Olive, 0, Vector2.Zero, Vector2.One, lEffect, 0);

            base.Draw(gameTime);
        }

        public Rectangle GetBoundingBox()
        {
            return mBoundingBox;
        }

        public Vector2 GetPosition()
        {
            return mPosition;
        }

        public bool Collides(GameObject pOther)
        {
            Rectangle lAbsoluteBBox =
                new Rectangle(pOther.GetBoundingBox().X + (int)pOther.GetPosition().X,
                              pOther.GetBoundingBox().Y + (int)pOther.GetPosition().Y,
                              pOther.GetBoundingBox().Width,
                              pOther.GetBoundingBox().Height);
            return this.Collides(lAbsoluteBBox);
        }

        public bool Collides(Rectangle pOtherRectangle)
        {
            Rectangle lAbsoluteBBox =
                new Rectangle(this.GetBoundingBox().X + (int)this.GetPosition().X,
                              this.GetBoundingBox().Y + (int)this.GetPosition().Y,
                              this.GetBoundingBox().Width,
                              this.GetBoundingBox().Height);

            return lAbsoluteBBox.Intersects(pOtherRectangle);
        }

        //******************************************

        public CollisionInfo CheckCollision(GameObject pOther)
        {
            CollisionInfo lInfo;
            lInfo.mSide = GameObject.Side.NONE;
            lInfo.mPenetrationVector = Vector2.Zero;

            //******

            Rectangle lAbsoluteBBoxOther =
                new Rectangle(pOther.GetBoundingBox().X + (int)pOther.GetPosition().X,
                              pOther.GetBoundingBox().Y + (int)pOther.GetPosition().Y,
                              pOther.GetBoundingBox().Width,
                              pOther.GetBoundingBox().Height);

            Rectangle lAbsoluteBBox =
                new Rectangle(this.GetBoundingBox().X + (int)this.GetPosition().X,
                              this.GetBoundingBox().Y + (int)this.GetPosition().Y,
                              this.GetBoundingBox().Width,
                              this.GetBoundingBox().Height);

            //*******

            Rectangle lIntersect = Rectangle.Intersect(lAbsoluteBBox, lAbsoluteBBoxOther);
            if (lIntersect.Width != 0 && lIntersect.Height != 0)
            {
                if (lIntersect.Top == lAbsoluteBBox.Top)
                {
                    lInfo.mSide |= Side.TOP;
                    lInfo.mPenetrationVector.Y = lIntersect.Top - lIntersect.Bottom - 1;
                }

                if (lIntersect.Top > lAbsoluteBBox.Top)
                {
                    lInfo.mSide |= Side.BOTTOM;
                    lInfo.mPenetrationVector.Y = lIntersect.Bottom - lIntersect.Top + 1;
                }

                if (lIntersect.Left == lAbsoluteBBox.Left)
                {
                    lInfo.mSide |= Side.LEFT;
                    lInfo.mPenetrationVector.X = lIntersect.Left - lIntersect.Right - 1;
                }

                if (lIntersect.Left > lAbsoluteBBox.Left)
                {
                    lInfo.mSide |= Side.RIGHT;
                    lInfo.mPenetrationVector.X = lIntersect.Right - lIntersect.Left + 1;
                }
            }

            return lInfo;
        }
    }
}
